/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entities;

import entities.exceptions.MissingRouteException;
import entities.exceptions.EmptyRouteException;
import entities.exceptions.RouteIndexOutOfRangeException;
import java.awt.Image;
import static entities.Actions.TransporterActions.*;

/**
 * Transporter Class
 * @author mateusz
 */
public class Transporter extends TransportRobot {

    /**
     * Creates transporter
     * @param factory   factory-mother
     * @param img       image
     * @param r         first route
     * @param myName    name
     */
    public Transporter(Factory factory, Image img, Route r, String myName) {
        super(factory, img, myName);
        init = true;
        this.maxCapacity = 12;
        this.currentSupply = getOppositeSupply(this.factory.getExtractedSupply()); // temporary to properties
        addRoute(r);
        updateProperties();
        updateLocation();
        t.start();
    }

    @Override
    protected void updateProperties() {
        super.updateProperties();
    }

    @Override
    protected void init() {
        super.init();
        action(null);
    }

    /**
     * Add route for next target to transporter
     * @param r
     */
    public void addRoute(Route r) {
        Route reversedRoute = new Route(r);
        reversedRoute.reverse(); // start this route from another factory
        try {
            reversedRoute.deleteCheckpoint(0, false);
        } catch (RouteIndexOutOfRangeException ex) {
        }

        // adds targets
        try {
            Tile anotherFactoryTile = r.getEnd();
            Tile factoryTile = this.factory.getAssociatedTile();

            addTarget(anotherFactoryTile, LEAVE_AND_LOAD);
            addTarget(factoryTile, LEAVE_SUPPLY_AND_DECIDE_WHAT_LOAD);

        } catch (EmptyRouteException ex) {
        }

        // add route to factory and back
        route.appends(r);
        route.appends(reversedRoute);
    }

    /**
     * Get opposite supply to passed
     * @param s supply
     * @return  opposite supply
     */
    public static Supplies getOppositeSupply(Supplies s) {
        if (s == Supplies.DIAMOND) {
            return Supplies.GAS;
        }
        return Supplies.DIAMOND;
    }

    @Override
    protected synchronized void action(Target target) {
        // another factory
        if (target != null && target.action == LEAVE_AND_LOAD) {
            Factory f = (Factory) target.tile.getAssociatedEntity();
            // if factory was not removed
            if (f != null) {
                unload(f, currentSupply, supplyUnits);
                load(f, getOppositeSupply(this.factory.getExtractedSupply()), maxCapacity);
            }
        } // in home
        else {
            // unload current units
            unload(this.factory, currentSupply, supplyUnits);
            
            Target nextTarget = null;
            while (isRunning()) {
                // spróbuj wziąć kolejny cel
                try {
                    nextTarget = getNextTarget();
                    break;
                } catch (IndexOutOfBoundsException e) {
                    // nie ma żadnego kolejnego celu - spróbuj pobrać losowy
                    while (isRunning()) {
                        try {
                            factory.newRouteForTransporter(this);
                            break; // break if route exists
                        } catch (MissingRouteException ex) {
                            goSleep();
                        }
                    }

                }
                if (!isRunning()) {
                    return;
                }
            }
            
            // get next target
            Supplies nextTargetSupply = ((Factory) nextTarget.tile.getAssociatedEntity()).getExtractedSupply();
            // load units
            load(this.factory, getOppositeSupply(nextTargetSupply), maxCapacity); // załaduj przeciwny do kolejnej fabryki
            // get fuel to track
            getFuel(this.factory);
        }
    }
    
    @Override
    public synchronized int kill(){
        super.kill();
        int units = factory.deleteTransporter(this);
        units += supplyUnits;
        
        return units;
    }
}
